using System;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Http;
using System.IO;

using ChatLib;
using System.Collections.Generic;

namespace Server
{
	

	public class Server : MarshalByRefObject, ChatLib.IServer
	{
		Database database = new Database();

		[Serializable]
		public class Letter
		{
			string from;
			string to;
			string message;
			
			public Letter(string from,string to,string message)
			{
				this.from=from;
				this.to=to;
				this.message=message;
			}

			public string From
			{
				get
				{
					return from;
				}
			}
			public string To
			{
				get
				{
					return to;
				}
			}
			public string Message
			{
				get
				{
					return message;
				}
			}


		}

		[Serializable]
		public class Task
		{
			string from;
			string to;
			string task;

			public Task(string from, string to, string task)
			{
				this.from = from;
				this.to = to;
				this.task = task;
			}

			public string From
			{
				get { return from; }
			}
			public string To
			{
				get { return to; }
			}
			public string TaskText
			{
				get { return task; }
			}


		}

		[Serializable]
		public class Screencast
		{
			internal string title;
			internal string ipAdress;

			public Screencast(string title, string ipAdress)
			{
				this.title = title;
				this.ipAdress = ipAdress;
			}
		}

		[Serializable]
		public class ScreencastMessage
		{
			internal string from;
			internal string message;

			public ScreencastMessage(string from, string message)
			{
				this.from = from;
				this.message = message;
			}
		}

		ArrayList letters = new ArrayList();
		ArrayList screencastConversation = new ArrayList();
		List<Screencast> screencasts = new List<Screencast>();
		
		//Constructor
		public Server()
		{
			database.Load();
		}

		//Methods
		public bool SignUp(string username,string password)
		{return database.Add(username,password);}
		public bool ChangePassword(string username,string curPassword,string newPassword)
		{return database.ChangePassword(username,curPassword,newPassword);}
		public bool SignIn(string username,string password,bool visible)
		{return database.SignIn(username,password,visible);}
		public bool SignOut(string username)
		{return database.SignOut(username);}
		public bool IsLoggedIn(string username)
		{return database.IsLoggedIn(username);}
		public bool IsVisible(string username)
		{ return database.IsVisible(username); }
		public bool AddContact(string username,string contact)
		{return database.AddContact(username,contact);}
		public bool RemoveContact(string username, string contact)
		{ return database.RemoveContact(username, contact); }
		public ArrayList GetContacts(string username)
		{return database.GetContacts(username);}
		
		private const int maxOfflineMessages = 100;

		public bool Send(string from,string to,string message)
		{
			if(database.ContactExists(to)==false)
				return false;

			if(database.IsLoggedIn(to))
				letters.Add(new Letter(from,to,message));
			else
			{
				database.offlineMessages.Add(new Letter(from,to,message));
				if(database.offlineMessages.Count>maxOfflineMessages)
				{
					database.offlineMessages.RemoveAt(0);
				}
				Console.WriteLine(database.Save());
			}
			return true;
		}
		public ArrayList ReceiveOffline(string to)
		{
			int length=database.offlineMessages.Count;
			ArrayList offlines = new ArrayList();
			for(int i = 0; i < length; i++)
			{
				if((database.offlineMessages[i] as Letter).To==to)
				{
					offlines.Add(new LetterReceive((database.offlineMessages[i] as Letter).Message,(database.offlineMessages[i] as Letter).From));
					database.offlineMessages.RemoveAt(i);
					i--;
					length--;
					continue;
				}
			}
			return offlines;
		}
		public LetterReceive Receive(string to)
		{
			int length = letters.Count;
			for(int i =0;i<length;i++)
			{ 
				if(((Letter)letters[i]).To==to)
				{
					LetterReceive lr = new LetterReceive(((Letter)letters[i]).Message,((Letter)letters[i]).From);
					letters.RemoveAt(i);
					return lr;
				}
			}
			return new LetterReceive("","");
		}

		public bool StartScreencast(string title, string ipAdress)
		{
			try
			{
				bool isStarted = false;

				foreach (Screencast sc in screencasts)
				{
					if (sc.ipAdress == ipAdress)
					{
						isStarted = true;
					}
				}

				if (isStarted == false)
				{
					Screencast scr = new Screencast(title, ipAdress);
					screencasts.Add(scr);

					Console.WriteLine("Screencast started at " + scr.ipAdress + " with title: \"" + scr.title + "\"");
				}

				return !isStarted;
			}
			catch
			{
				return false;
			}
		}
		public void StopScreencast(string ipAdress)
		{
			try
			{
				//Screencast scr = new Screencast(title, ipAdress);
				foreach (Screencast scr in screencasts)
				{
					if (scr.ipAdress == ipAdress)
						screencasts.Remove(scr);

					Console.WriteLine("Screencast \"" + scr.title + "\" stopped. IP: " + scr.ipAdress);
				}
			}
			catch{}
			
		}
		public ArrayList GetScreencasts()
		{
			ArrayList AL = new ArrayList();
			foreach (Screencast s in screencasts)
			{
				AL.Add(s.ipAdress + " : " + s.title);
			}

			return AL;
		}

		public void SendScreencastMessage(string username, string message)
		{
			screencastConversation.Add(new ScreencastMessage(username, message));
		}

		public ArrayList GetScreencastConversation()
		{
			ArrayList AL = new ArrayList();

			foreach (ScreencastMessage sm in screencastConversation)
			{
				AL.Add(sm.from + ": " + sm.message);
			}

			return AL;
		}


		public void SendTask(string from, string to, string task)
		{
			database.tasks.Add(new Task(from, to, task));
			Console.WriteLine("Task \"" + task + "\" added to user \"" + to + "\":");
			Console.WriteLine(database.Save());
		}
		public void CompleteTask(string username, string task)
		{
			int length = database.tasks.Count;
			for (int i = 0; i < length; i++)
			{
				if ((database.tasks[i] as Task).TaskText == task && (database.tasks[i] as Task).To == username)
				{
					database.tasks.RemoveAt(i);
					i--;
					length--;
					Console.WriteLine("Task \"" + task + "\" completed by user \"" + username + "\":");
					Console.WriteLine(database.Save());
					continue;
				}
			}
		}
		public ArrayList GetTasks(string username)
		{
			ArrayList AL = new ArrayList();

			foreach (Task t in database.tasks)
			{
				if (t.To == username)
					AL.Add(t.TaskText);
			}

			return AL;
		}

		internal Database Database
		{
			get
			{
				throw new System.NotImplementedException();
			}
			set
			{
			}
		}

	}
}